package com.yyy.tcc.service.compensation;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * 并发原子操作示例类
 * 演示AtomicInteger的基本使用和CAS操作原理
 * 以及AtomicStampedReference解决ABA问题
 */
public class T {
    // 创建原子计数器，初始值为0
    private static AtomicInteger count = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        // 基本自增操作演示
//        AtomicInteger successCount = new AtomicInteger(0);
//        System.out.println(successCount);  // 输出初始值0
//        successCount.incrementAndGet();     // 原子自增操作
//        System.out.println(successCount);  // 输出自增后的值1
//
//        // 并发自增测试：创建10000个线程同时执行自增操作
//        for(int i = 0; i < 10000; i++){
//            new Thread(new Runnable() {
//                @Override
//                public void run() {
//                    count.incrementAndGet(); // 原子自增操作，保证线程安全
//                }
//            }).start();
//        }
//
//        // 等待2秒，确保所有线程执行完成
//        Thread.sleep(2000);
//
//        // 输出最终结果，验证并发安全性
//        System.out.println(count);
//
//        // 测试CAS底层实现
//        casIncrement();
//
//        // 测试AtomicStampedReference解决ABA问题
//        atomicStampedReferenceExample();

        AtomicStampedReference<Integer> ref = new AtomicStampedReference<>(1, 0);
        System.out.println(ref.getReference());
        int[] stampHolder = {0};
        ref.compareAndSet(1, 2, stampHolder[0], stampHolder[0] + 1);
        // 比较并设置值，同时更新版本号
        System.out.println(ref.getReference());

    }

    /**
     * 模拟CAS（Compare And Swap）操作的底层实现
     * CAS是一种无锁算法，通过比较和替换来保证原子性
     */
    private static void casIncrement() {
        int expectedValue;  // 期望值
        int newValue;      // 新值
        do {
            expectedValue = count.get();  // 获取当前值
            newValue = expectedValue + 1; // 计算新值
            // 如果当前值等于期望值，则更新为新值，否则重试
        } while (!count.compareAndSet(expectedValue, newValue));

        System.out.println("CAS increment result: " + count.get());
    }

    /**
     * 演示AtomicStampedReference解决ABA问题
     * ABA问题：一个值从A变成B，又变回A，使用版本号可以检测到这个变化
     */
    private static void atomicStampedReferenceExample() throws InterruptedException {
        // 创建带版本号的原子引用，初始值为100，初始版本号为0
        AtomicStampedReference<Integer> atomicStampedRef = new AtomicStampedReference<>(100, 0);

        // 线程1：执行ABA操作
        Thread thread1 = new Thread(() -> {
            try {
                // 获取当前版本号
                int stamp = atomicStampedRef.getStamp();
                System.out.println("Thread1 read value: " + atomicStampedRef.getReference() + ", stamp: " + stamp);

                Thread.sleep(1000); // 等待1秒

                // 将100改为101，版本号+1
                atomicStampedRef.compareAndSet(100, 101, stamp, stamp + 1);
                System.out.println("Thread1 update to 101");

                // 将101改回100，版本号再+1
                atomicStampedRef.compareAndSet(101, 100, stamp + 1, stamp + 2);
                System.out.println("Thread1 update back to 100");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 线程2：尝试更新操作
        Thread thread2 = new Thread(() -> {
            try {
                // 获取当前版本号
                int stamp = atomicStampedRef.getStamp();
                System.out.println("Thread2 read value: " + atomicStampedRef.getReference() + ", stamp: " + stamp);

                Thread.sleep(2000); // 等待2秒，让线程1完成ABA操作

                // 尝试更新，由于版本号已变化，更新会失败
                boolean result = atomicStampedRef.compareAndSet(100, 102, stamp, stamp + 1);
                System.out.println("Thread2 update to 102, result: " + result);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 启动线程
        thread1.start();
        thread2.start();

        // 等待两个线程执行完成
        thread1.join();
        thread2.join();

        // 输出最终结果
        System.out.println("Final value: " + atomicStampedRef.getReference() +
                         ", stamp: " + atomicStampedRef.getStamp());
    }
}
